#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from pycparser.plyparser import Coord
from ctools.common.treenode import TNode

'''common node'''
class Node(TNode):
    """ Abstract base class """

    def __init__(self, type:str='', name:str='', coord:Coord=None, **kwargs) -> None:
        super().__init__(name)
        # param/struct/union/func
        self.type = type
        self.coord = coord
        for k, v in kwargs.items():
            setattr(self, k, v)

    def __str__(self):
        return f"{self.__class__.__name__}({self.name} {str(self.coord)})"

class _BlockNode(Node):
    def __init__(self, type:str, name:str, body, coord:Coord=None, **kwargs) -> None:
        super().__init__(type, name, coord, **kwargs)
        self.body = body

class UnkownNode(Node):
    def __init__(self, name:str, coord:Coord=None, **kwargs) -> None:
        super().__init__('unkown', name, coord, **kwargs)

'''node for c'''
class ParamNode(Node):
    def __init__(self, name:str, val, coord:Coord=None, **kwargs) -> None:
        super().__init__('param', name, coord, **kwargs)
        self.value = val

class TypeNode(Node):
    def __init__(self, typename, name, parent=None, coord=None, **kwargs):
        super().__init__('typedecl', name, coord, **kwargs)
        self.typename = typename
        self.set_parent(parent)

    def __str__(self):
        return f"{self.__class__.__name__}({self.typename} {str(self.coord)})"

class AliasNode(Node):
    def __init__(self, name:str, target:str, coord:Coord=None, **kwargs) -> None:
        super().__init__('alias', name, coord, **kwargs)
        self.target = target

class KeepNode(_BlockNode):
    def __init__(self, name:str, body, coord:Coord=None, **kwargs) -> None:
        super().__init__('keep', name, body, coord, **kwargs)

class FuncNode(Node):
    def __init__(self, name:str, coord:Coord=None, **kwargs) -> None:
        super().__init__('function', name, coord, **kwargs)

class CTreeNode(_BlockNode):
    def __init__(self, name:str, body, coord:Coord=None, **kwargs) -> None:
        super().__init__('ctree', name, body, coord, **kwargs)

'''node for type'''
class StructVarNode(Node):
    def __init__(self, name:str, typename:str, varlabel:str, coord:Coord=None, **kwargs) -> None:
        super().__init__('param', name, coord, **kwargs)
        self.typename = typename
        self.varlabel = varlabel

'''node for func'''
class VarNode(Node): pass

class CallNode(Node):
    def __init__(self, name: str = '', coord: Coord = None, **kwargs) -> None:
        super().__init__('call', name, coord, **kwargs)

class LinkNode(Node):
    def __init__(self, left:str, right:str, linkop:str,
                jump:int=0, manual=True, coord:Coord=None, **kwargs) -> None:
        _dirs = {
            'forward':  '->',
            'back':     '<-',
            'none':     '-',
            'both':     '+',
        }
        name = "{} {} {}".format(left, linkop, right)
        super().__init__('link', name, coord, **kwargs)
        self.left = left
        self.right = right
        self.linkop = linkop
        self.dir, self.style = self.get_dir_style(linkop)
        self.jump = jump
        self.manual = manual

    @staticmethod
    def get_dir_style(op):
        if op == '~':
            return 'none', 'invis'

        d_dict = {
            '+': 'both',
            '-': 'none',
            '>': 'forward',
            '<': 'back',
        }
        s_dict = {
            1: 'solid',
            2: 'dashed',
            3: 'dotted',
            4: 'bold',
            5: 'tapered',
        }

        return d_dict[op[0]], s_dict[len(op)]

class TreeCodeNode(_BlockNode):
    def __init__(self, name:str, body, coord:Coord=None, **kwargs) -> None:
        super().__init__('treecode', name, body, coord, **kwargs)
